package com.hksj.Intelligentmanagement.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hksj.Intelligentmanagement.common.Rest;
import com.hksj.Intelligentmanagement.common.Result;
import com.hksj.Intelligentmanagement.dto.NurseDTO;
import com.hksj.Intelligentmanagement.entity.NurseEntity;
import com.hksj.Intelligentmanagement.entity.UserRegion;
import com.hksj.Intelligentmanagement.mapper.NurseMapper;
import com.hksj.Intelligentmanagement.mapper.ShiftsMapper;
import com.hksj.Intelligentmanagement.vo.ClassesVo;
import com.hksj.Intelligentmanagement.vo.NurseSimpleVo;
import com.hksj.Intelligentmanagement.vo.NurseVo;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class NurseService extends ServiceImpl<NurseMapper, NurseEntity> {

    @Autowired
    private NurseMapper nurseMapper;

    @Autowired
    private Mapper mapper;

    @Autowired
    private ShiftsMapper shiftsMapper;

    @Autowired
    private UserRegionService userRegionService;

    /**
     * 新增人员信息
     * @param nurseDTO 人员类型  1 = 护士  2 = 麻醉
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Rest createNurse(NurseDTO nurseDTO){

        //根据工号查询是否存在
        LambdaQueryWrapper<NurseEntity> wrapper = new QueryWrapper<NurseEntity>().lambda()
                .eq(NurseEntity::getEmployeeNumber, nurseDTO.getEmployeeNumber())
                .eq(NurseEntity::getDelFlag,0)
                .eq(NurseEntity::getType,nurseDTO.getType());
        NurseEntity nurseEntity = nurseMapper.selectOne(wrapper);

        if (!Objects.isNull(nurseEntity)){
            //已存在
            return Rest.fail("输入的工号已存在,请重新输入");
        }

        //不存在 插入
        //将nurseDTO转化为nurseEntity
        nurseEntity = mapper.map(nurseDTO, NurseEntity.class);

        nurseMapper.insert(nurseEntity);

        saveUserRegion(nurseDTO.getRegions(),nurseEntity.getId(),nurseEntity.getType());

        return Rest.ok("新增人员信息成功");
    }

    public void saveUserRegion(List<String> regions,String userId,Integer type){
        if (!ObjectUtils.isEmpty(regions)){
            List<UserRegion> userRegions = new ArrayList<>();
            for (String regionId : regions) {
                UserRegion userRegion = new UserRegion();
                userRegion.setUserId(userId);
                userRegion.setRegionId(regionId);
                userRegion.setType(type);
                userRegions.add(userRegion);
            }
            userRegionService.saveBatch(userRegions);
        }
    }

    public void removeUserRegion(String userId,Integer type){
        userRegionService.lambdaUpdate()
                .eq(UserRegion::getUserId,userId)
                .eq(UserRegion::getType,type)
                .remove();
    }

    public void updateUserRegion(List<String> regions,String userId,Integer type){
        removeUserRegion(userId,type);
        saveUserRegion(regions,userId,type);
    }

    //删除护士
    public Rest deleteNurse(String id){

        //根据id查询护士信息是否存在
        NurseEntity nurseEntity = nurseMapper.selectById(id);

        if (Objects.isNull(nurseEntity)){
            //不存在
            return Rest.fail("id输入有误,删除失败");
        }

        //存在,逻辑删除
        nurseMapper.deleteById(id);

        removeUserRegion(nurseEntity.getId(),nurseEntity.getType());

        return Rest.ok("删除人员信息成功");

    }

    //修改护士
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Rest updateNurse(NurseDTO nurseDTO){
        LambdaQueryWrapper<NurseEntity> query = new QueryWrapper<NurseEntity>().lambda()
                .eq(NurseEntity::getEmployeeNumber, nurseDTO.getEmployeeNumber())
                .eq(NurseEntity::getDelFlag, 0)
                .ne(NurseEntity::getId,nurseDTO.getId());
        int count = count(query);
        if (count > 0){
            return Rest.fail("输入的工号已存在,请重新输入");
        }

        //存在
        //将nurseDTO转化为nurseEntity
        NurseEntity nurseEntity = mapper.map(nurseDTO,NurseEntity.class);

        //做更新
        nurseMapper.updateById(nurseEntity);

        updateUserRegion(nurseDTO.getRegions(),nurseDTO.getId(),nurseDTO.getType());

        return Rest.ok("更新人员信息成功");

    }

    //根据工号查询护士信息
    public Result queryNurseByEmployeeNumber(int employeeNumber){
        //构建查询语句
        LambdaQueryWrapper<NurseEntity> wrapper = new QueryWrapper<NurseEntity>().lambda()
                .eq(NurseEntity::getEmployeeNumber, employeeNumber);

        //通过wrapper查询护士信息
        NurseEntity nurseEntity = nurseMapper.selectOne(wrapper);

        return Result.ok(nurseEntity);
    }

    //动态分页查询护士列表
    public IPage<NurseVo> queryNurseListByPage(NurseDTO nurseDTO){

        //创建一个分页实例
        IPage<NurseVo> page = new Page<>(nurseDTO.getPageNum(),nurseDTO.getPageSize());

        //分页查询
        List<NurseVo> nurseEntities = nurseMapper.queryNurseListByPage(page, nurseDTO);

        //将分页结果设置到分页中
        page.setRecords(nurseEntities);

        //返回分页
        return page;
    }

    //由时间查询当天值班护士
   public List<NurseVo> queryNurseListByOperationTime(NurseDTO nurseDTO){
        //查询所有班次记录
       List<ClassesVo> classesVos = shiftsMapper.queryAllClasses();

       //使用stream流将查询出的班次记录set到classesList中
       List<NurseVo> nurseVos = nurseMapper.queryNurseListByOperationTime(nurseDTO);

       //将nurseVos转为流并且将班次设置到classesList中
       List<NurseVo> newNurseVos = nurseVos.stream()
               //对nurseVos中的元素进行遍历消费
               .peek(nurseVo -> nurseVo.setClassesList(
                       classesVos.stream()
                               .filter(classesVo -> nurseVo.getSchedulingId().contains(classesVo.getId()))//将包含在schedulingId中的classesVo设置到ClassesList中
                               .collect(Collectors.toList())//回收流
               ))
               .collect(Collectors.toList());//回收流
       //若前端传递的operationTime为空则查询所有的护士
       if (!StringUtils.hasText(nurseDTO.getOperationTime())){
           return  newNurseVos;
       }

       //若前端传递的operationTime不为空则查询满足排班要求的护士
       List<NurseVo> vos = newNurseVos.stream() //将查询出的护士列表转为stream流
               //进行条件过滤
               //判断集合是否为空,为空说明该护士的班次都不符合要求直接舍弃该护士、不为空说明该护士至少有一个班次是符合要求的
               .filter(nurseVo -> !CollectionUtils.isEmpty(nurseVo.getClassesList().stream()//将护士班次列表转为stream流
                       .filter(classesVo -> classesVo.getStartTime().compareTo(nurseDTO.getOperationTime()) < 0 &&
                               classesVo.getEndTime().compareTo(nurseDTO.getOperationTime()) > 0)//过滤掉不满足 手术开台时间不在[班次开始时间,班次结束时间]内的那些护士
                       .collect(Collectors.toList()))//收集流并转为List集合
               )
               .collect(Collectors.toList());//将stream流转为List集合

       //返回处理后的结果
       return vos;
   }

    public List<NurseSimpleVo> listNurse(String nurseName, Integer type) {
        return nurseMapper.listNurse(nurseName,type);
    }

    @Transactional(readOnly = true)
    public IPage<NurseVo> pageNurse(Page<NurseVo> page, String nurseName, String employeeNumber,String nurseLevelId,String status,Integer type) {
        List<NurseVo> nurseVos =  nurseMapper.pageNurse(page,nurseName,employeeNumber,nurseLevelId,status,type);
        page.setRecords(nurseVos);
//        for (NurseVo nurseVo : nurseVos) {
//            List<UserRegionVo> userRegionVos = userRegionService.getRegionByUserId(nurseVo.getId());
//            nurseVo.setRegions(userRegionVos);
//        }
        return page;
    }

    public List<NurseSimpleVo> listUnscheduledNurse(String operateTime, Integer type){
        return baseMapper.listUnscheduledNurse(operateTime,type);
    }
}
